package com.smart.client.core.client;

import com.smart.client.core.handler.NettyChannelInboundHandlerAdapter;
import com.smart.client.core.listener.ConnectionListener;
import com.smart.client.core.notice.EventNotice;
import com.smart.client.properties.TcpClientProperties;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

/**
 * Created By Li Jiaxi
 * <br/>Date: 2023/4/12 10:35
 * <br/>Description:
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class NettyClient implements IClient {

    /**
     * 注入配置
     */
    private final TcpClientProperties tcpClientProperties;

    /**
     * 注入通道初始化
     */
    // private final ChannelInitializer<Channel> channelInitializer;
    private final EventNotice eventNotice;
    /**
     * 注入重连监听器
     */
    // private final ChannelFutureListener connectionListener;

    /**
     * 客户端的NIO线程组
     */
    private EventLoopGroup eventLoopGroup;

    /**
     * Bootstrap 是一个启动NIO服务的辅助启动类 客户端的
     */
    private Bootstrap bootstrap;

    /**
     * 连接tcp服务器
     *
     * @throws Exception 异常
     */
    protected void connect() throws Exception {
        // 设置group
        bootstrap = bootstrap.group(eventLoopGroup);
        // 关联客户端通道
        bootstrap = bootstrap.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true);
        // 设置 I/O处理类,主要用于网络I/O事件，记录日志，编码、解码消息
        bootstrap = bootstrap.handler(new NettyChannelInboundHandlerAdapter(eventNotice, this));
        // 连接服务端
        ChannelFuture f = bootstrap.connect(tcpClientProperties.getIp(), tcpClientProperties.getPort()).addListener(new ConnectionListener(this)).sync();
        log.info("=====>>>> Start TCP Netty Client Success ... ");
        // 等待连接端口关闭
        f.channel().closeFuture().sync();
    }

    @Override
    public void start() throws Exception {
        if (!tcpClientProperties.isEnabled()) {
            log.info("=====>>>> TCP Netty Client is disabled ... ");
            return;
        }
        log.info("=====>>>> Initial TCP Netty Client ... ");
        eventLoopGroup = tcpClientProperties.isUseEpoll() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        this.connect();
    }

    @Override
    public void reconnect() throws Exception {
        log.info("=====>>>> Reconnect TCP Netty Client ... ");
        ChannelFuture f = bootstrap.connect(tcpClientProperties.getIp(), tcpClientProperties.getPort()).addListener(new ConnectionListener(this)).sync();
        log.info("=====>>>> Reconnect TCP Netty Client Success ... ");
        // 等待连接端口关闭
        f.channel().closeFuture().sync();
    }

    @PreDestroy
    @Override
    public void destroy() throws InterruptedException {
        eventLoopGroup.shutdownGracefully();
        log.info("=====>>>> Release TCP Netty Client ... ");
    }
}
